from libcpp.vector cimport vector


cdef extern from "ClipperLib/clipper.hpp" namespace "ClipperLib":
    # enum ClipType { ctIntersection, ctUnion, ctDifference, ctXor };
    cdef enum ClipType:
        ctIntersection = 1,
        ctUnion = 2,
        ctDifference = 3,
        ctXor = 4

    # enum PolyType { ptSubject, ptClip };
    cdef enum PolyType:
        ptSubject = 1,
        ptClip = 2

    # By far the most widely used winding rules for polygon filling are
    # EvenOdd &NonZero (GDI, GDI+, XLib, OpenGL, Cairo, AGG, Quartz, SVG, Gr32)
    # Others rules include Positive, Negative and ABS_GTR_EQ_TWO (only in OpenGL)
    # see http://glprogramming.com/red/chapter11.html
    # enum PolyFillType { pftEvenOdd, pftNonZero, pftPositive, pftNegative };
    cdef enum PolyFillType:
        pftEvenOdd = 1,
        pftNonZero = 2,
        pftPositive = 3,
        pftNegative = 4

    # The correct type definition is taken from cpp source, so
    # the use_int32 is handled correctly.
    # If you need 32 bit ints, just uncomment //#define use_int32 in clipper.hpp
    # and recompile
    ctypedef signed long long cInt

    # TODO: handle "use_xyz" that adds Z coordinate
    cdef struct IntPoint:
        cInt X
        cInt Y

    #typedef std::vector< IntPoint > Path;
    ctypedef vector[IntPoint] Path

    #typedef std::vector< Path > Paths;
    ctypedef vector[Path] Paths

    ctypedef vector[PolyNode*] PolyNodes

    cdef cppclass PolyNode:
        PolyNode()
        Path Contour
        PolyNodes Childs
        PolyNode *Parent
        PolyNode *GetNext()
        bint IsHole()
        bint IsOpen()
        int ChildCount()

    cdef cppclass PolyTree(PolyNode):
        PolyTree()
        PolyNode& GetFirst()
        void Clear()
        int Total()

    #enum InitOptions {ioReverseSolution = 1, ioStrictlySimple = 2, ioPreserveCollinear = 4};
    cdef enum InitOptions:
        ioReverseSolution = 1,
        ioStrictlySimple = 2,
        ioPreserveCollinear = 4

    #enum JoinType { jtSquare, jtRound, jtMiter };
    cdef enum JoinType:
        jtSquare = 1,
        jtRound = 2,
        jtMiter = 3

    #enum EndType {etClosedPolygon, etClosedLine, etOpenButt, etOpenSquare, etOpenRound};
    cdef enum EndType:
        etClosedPolygon = 1,
        etClosedLine = 2,
        etOpenButt = 3,
        etOpenSquare = 4,
        etOpenRound = 5

    cdef struct IntRect:
        cInt left
        cInt top
        cInt right
        cInt bottom

    cdef cppclass Clipper:
        Clipper(int initOptions)
        Clipper()
        #~Clipper()
        void Clear()
        bint Execute(ClipType clipType, Paths &solution, PolyFillType subjFillType, PolyFillType clipFillType)
        bint Execute(ClipType clipType, PolyTree &solution, PolyFillType subjFillType, PolyFillType clipFillType)
        bint ReverseSolution()
        void ReverseSolution(bint value)
        bint StrictlySimple()
        void StrictlySimple(bint value)
        bint PreserveCollinear()
        void PreserveCollinear(bint value)
        bint AddPath(Path &path, PolyType polyType, bint closed)
        bint AddPaths(Paths &paths, PolyType polyType, bint closed)
        IntRect GetBounds()

    cdef cppclass ClipperOffset:
        ClipperOffset(double miterLimit, double roundPrecision)
        ClipperOffset(double miterLimit)
        ClipperOffset()
        #~ClipperOffset()
        void AddPath(Path &path, JoinType joinType, EndType endType)
        void AddPaths(Paths &paths, JoinType joinType, EndType endType)
        void Execute(Paths &solution, double delta)
        void Execute(PolyTree &solution, double delta)
        void Clear()
        double MiterLimit
        double ArcTolerance

    # prefixes are added to original functions to prevent naming collisions
    bint Orientation(const Path &poly)
    double Area(const Path &poly)
    int PointInPolygon(const IntPoint &pt, const Path &path)

    # In the following 4 functions default values for fillType and distance were removed
    # because it caused a bug in C++ code generated by Cython.
    # See Cython bug report: http://trac.cython.org/ticket/816
    void SimplifyPolygon(const Path &in_poly, Paths &out_polys, PolyFillType fillType)
    void SimplifyPolygons(const Paths &in_polys, Paths &out_polys, PolyFillType fillType)
    void CleanPolygon(const Path& in_poly, Path& out_poly, double distance)
    void CleanPolygons(Paths& polys, double distance)

    void MinkowskiSum(const Path& pattern, const Path& path, Paths& solution, bint pathIsClosed)
    void MinkowskiSum(const Path& pattern, const Paths& paths, Paths& solution, bint pathIsClosed)
    void MinkowskiDiff(const Path& poly1, const Path& poly2, Paths& solution)

    void PolyTreeToPaths(const PolyTree& polytree, Paths& paths)
    void ClosedPathsFromPolyTree(const PolyTree& polytree, Paths& paths)
    void OpenPathsFromPolyTree(PolyTree& polytree, Paths& paths)

    void ReversePath(Path& p)
    void ReversePaths(Paths& p)
